/*
 * This file is part of din.
 *
 * din is copyright (c) 2006 - 2012 S Jagannathan <jag@dinisnoise.org>
 * For more information, please visit http://dinisnoise.org
 *
 * din is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * din is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with din.  If not, see <http://www.gnu.org/licenses/>.
 *
*/

#ifndef __widget
#define __widget

#include "box.h"
#include "color.h"

#include <vector>
#include <string>
#include <fstream>

extern int rmb;

struct ui;
struct widget;

struct mover {
	
	widget& w; // target widget
	int* pmb; // mouse button that moves widget
	int mb_clicked; // is mouse button clicked
	int move; // 1 - widget is moving, 0 - not
	int prevx, prevy; // previous mouse position
	
	mover (widget& ww, int* pb = &rmb);
	int handle_input ();
	
};

typedef std::vector<widget *>::size_type size_vw;

class widget { // ui widget

	std::string name; // name of this widget
		
	box<int> extents; // extents of the bounding box around this widget

	color clr; // color
	
	int posx, posy; // position in screen space

	int visible_; // visible?

	int hover; // mouse over widget?

	std::vector <ui *> screens; // screens where shown
	
	std::vector<widget *> children; // widget's children (ie other widgets; a gui hierarchy)
	
	int enable_; // enabled?
	
	// helper to handle move with mouse
	//
	friend struct mover;
	int moveable; // moveable?
	mover movr; // handles move
	
	public:

		static widget* focus; // widget with input focus; only 1 at a time ie only 1 widget can receive input.

		widget (int l = 0, int b = 0, int r = 0, int t = 0);
		
		const std::string& get_name () {return name;}
		void set_name (const std::string& _name) {name = _name;}
		
		void set_parent (widget* w);

		const box<int>& get_extents () const {return extents;}
		void set_extents (int l, int b, int r, int t);
		void set_extents (const box<int>& ext) { extents = ext;}

		virtual void set_pos (int x, int y);
		virtual void get_pos (int& x, int& y);

		int is_moveable () const {return moveable;}
		void set_moveable (int m, int* pmb = &rmb) {moveable = m; movr.pmb = pmb;}
		void move (int dx, int dy);

		void set_color (float r, float g, float b) { clr.r = r; clr.g = g; clr.b = b; }
		void set_color (const color& c) {clr.r = c.r; clr.g = c.g; clr.b = c.b; }
		const color& get_color () const {return clr;}

		inline int hovering () {return hover;}
		
		void add_screen (ui* scr);
		int is_screen (ui* scr);
		const std::vector<ui*>& get_screens () const {return screens;}

		void add_child (widget *w);
		
		int visible () const {return visible_;}
		void show ();
		void hide ();
				
		void enable (int e) {enable_ = e;} 
		int enabled () const {return enable_;}
		
		virtual int handle_input ();	
		virtual void draw ();
		virtual void save (std::ofstream& file);

		void draw_bbox ();
		
};

// listeners for widgets
//
template <typename W> struct change_listener {
	virtual void changed (W& w) = 0;
};

#endif
